

/******************************************************************************
 *
 *
 * File:	USB_GUI_0100_M52259DEMO.c
 *
 *
 ******************************************************************************/
 
 /*****************************************************************************
  *
  *
  * This is a demonstration program showing USB communications using
  *		usb_logger.c. For a description of its operation see
  *		USB_GUI_0100 rev100.doc.
  *
  *
  *****************************************************************************/
  
  

#include <mqx.h>
#include <bsp.h>
#include "main.h"
#include <usb_logger.h>
#include <USB_GUI_0100_M52259DEMO.h>


/*******************************************************************************
 *
 * Constants
 *
 ******************************************************************************/
 #define MY_TRIGGER_0 ADC_TRIGGER_1
 #define MY_TRIGGER_1 ADC_TRIGGER_2



/*******************************************************************************
 *
 *	GLOBAL VARIABLES
 *
 *******************************************************************************/
 
 /* 
  *		Control structures for EP1 & EP3 OUT (receive) packet transactions.
  *		These are declared in usb_logger.c
  */
 extern EP_RX_CTRL ep1_rx_ctrl;
 extern EP_RX_CTRL ep3_rx_ctrl;
 
 /* Logger Global Variable Structure. */
 extern LOGGER_GLOBAL_VARIABLE_STRUCT g_logger;

 
 /* Handles for operating the LEDs LED(1:2),SW(1:2) and ADCs. */
 /* Ref: Freescale MQX I/O Drivers Users Guide (MQXIOUG.pdf). Chapter 7 */
 
 FILE_PTR led_file1, led_file2, led_file3, sw_file, result_file; 
 FILE_PTR adc_file1, adc_file2, adc_file3;
 
 /*
  *	Arrays for operating the LEDs and switches.
  */
 
 /* LED Arrays */
 
 /* Declare arrays of type 
 	GPIO_PIN_STRUCT (...\lib\m52259demo.cw\mqx\io_gpio.h) 
 		which define the LED pins in the format 
   		<port_name> | <pin_number> | <additional_flage>.
 	Ref: MQX I/O User's Guide "7.5 Opening GPIO Device"
  */
 
 /* Define an array listing all the LEDs. It will be used to open
 		a GPIO device driver for controlling the LEDs. */
 GPIO_PIN_STRUCT pins1[] = 
 {
 	/* Open file to control LEDs(1:4) and initialise their status to OFF.
 		Here <additional_flags> = GPIO_PIN_STATUS_0 will clear the pin. */
 	BSP_LED1 | GPIO_PIN_STATUS_0,	// 
 	BSP_LED2 | GPIO_PIN_STATUS_0,
 	BSP_LED3 | GPIO_PIN_STATUS_0,
 	BSP_LED4 | GPIO_PIN_STATUS_0,
 	GPIO_LIST_END
 };
 
 /* Define arrays for writing to the LEDs individually.
 	These are used with the Generic IOCTL Commands. */
 
 /* For controlling LED1 individually */
  GPIO_PIN_STRUCT pins2[] = 
 {
 	BSP_LED1,
 	GPIO_LIST_END
 };
 
 /* For controlling LED2 individually */
  GPIO_PIN_STRUCT pins3[] = 
 {
 	BSP_LED2,
 	GPIO_LIST_END
 };
 
 /* For controlling LED3 individually */
  GPIO_PIN_STRUCT pins4[] = 
 {
 	BSP_LED3,
 	GPIO_LIST_END
 };
 
 /* For controlling LED4 individually */
  GPIO_PIN_STRUCT pins5[] = 
 {
 	BSP_LED4,
 	GPIO_LIST_END
 };
 
 
 /* Define an array listing all the Switches. It will be used to open
 		a GPIO device driver for controlling the Switches. */
 GPIO_PIN_STRUCT pins6[] =
 {
 	BSP_BUTTON1 | GPIO_PIN_IRQ_FALLING,	// Interrupt on falling edge
 	BSP_BUTTON2 | GPIO_PIN_IRQ_FALLING,
 	GPIO_LIST_END
 };
 
 
 /* 
  * For controlling the Analog-To-Digital Converter. 
  */
 
 /* ADC device init struct */
 const ADC_INIT_STRUCT adc_init = {
    ADC_RESOLUTION_DEFAULT,     /* resolution */
 };
 
 /* Using AN0 - M52259DEMOCOM connector J4 pin 29. */
 /* Sampling will be initiated upon receipt of these parameters. */
 /* Once triggered samples continuously at 1kHz. */
const ADC_INIT_CHANNEL_STRUCT adc_channel_param0 = 
{
    ADC_SOURCE_AN0, /* Using ADC channel 0 */
    /* Sample one sequence only, immediatly upon receipt of a trigger. */
    ADC_CHANNEL_MEASURE_LOOP | ADC_CHANNEL_START_TRIGGERED, 
    1,              /* number of samples in one run sequence */
    0,         		/* time offset from trigger point in us */
    1000,         	/* period in us (= 0.001 sec) */
    0x10000,        /* scale range of result (not used now) */
    1,              /* circular buffer size (sample count) */
    MY_TRIGGER_0,   /* logical trigger ID that starts this ADC channel */
#if MQX_USE_LWEVENTS
    NULL
#endif
};


 /* Using AN1 - M52259DEMOCOM connector J4 pin 30. */
 /* Sampling will be initiated upon receipt of these parameters. */
 /* Once triggered samples continuously at 1kHz. */
const ADC_INIT_CHANNEL_STRUCT adc_channel_param1 = 
{
    ADC_SOURCE_AN1, /* Using ADC channel 1 */
    /* Sample one sequence only, immediatly upon receipt of a trigger. */
    ADC_CHANNEL_MEASURE_LOOP | ADC_CHANNEL_START_TRIGGERED, 
    1,              /* number of samples in one run sequence */
    0,         		/* time offset from trigger point in us */
    1000,         	/* period in us (= 0.001 sec) */
    0x10000,        /* scale range of result (not used now) */
    1,              /* circular buffer size (sample count) */
    MY_TRIGGER_1,   /* logical trigger ID that starts this ADC channel */
#if MQX_USE_LWEVENTS
    NULL
#endif
};

uint_8 adc_triggered = 0;




/******************************************************************************
 *  
 *   @name        TestApp_Init
 * 
 *   @brief       This function is the entry for USB Logger (or other usuage)
 * 
 *   @param       None
 * 
 *   @return      None
 **                
 *****************************************************************************/
void TestApp_Init(void)
{       
    
    USB_Class_LOGGER_Init();
    
    /* Initialise the endpoint control structure */
    Endpoint_Init();
    
    
    /* Initialise the ADC device */
    ADC_Init();
    
    /* Initialise control of LED(1:2) */
    LED_1_4_Init();
    
    /* Wait loop */
    while (TRUE)
    {
    	/* Check for the arrival of a packet at EP1 or EP3 */
    	EP1_3_PACKET_REC();
    	
    	/* Repeat every 100mSec. */
    	_time_delay(100);
    }
  
} 


/****************************************************************************
 *
 * Function Name  : Endpoint_Init
 * Returned Value : None
 *
 * Operation	  : Initialises the structures for controlling 
 *                   endpoint transactions.
 *					Structures store data packets received at OUT endpoints.
 *
 ***************************************************************************/
 void Endpoint_Init(void)
 {
 	
 	EP_RX_CTRL_PTR epctrlPtr;		// Pointer to an EP control structure
 	
 	/* Initialise EP1 structure */
 	epctrlPtr = &ep1_rx_ctrl;		// Set the pointer to the EP1 control structure
 	epctrlPtr->pkt_rec = FALSE;	// Clear packet received flag
 	epctrlPtr->overrun_err = FALSE;	// Clear overrun error flag
 	epctrlPtr->len = 0x00;				// Received packet length zero
 	
 	/* Initialise EP3 structure */
 	epctrlPtr = &ep3_rx_ctrl;		// Set the pointer to the EP3 control structure
 	epctrlPtr->pkt_rec = FALSE;	// Clear packet received flag
 	epctrlPtr->overrun_err = FALSE;	// Clear overrun error flag
 	epctrlPtr->len = 0x00;				// Received packet length zero
 	
 	
 }
 
/****************************************************************************
 *
 * Function Name  : LED_1_4_Init
 * Returned Value : None
 *
 *	Operation:		Open a GPIO device for writing to the LEDs.
 *					Specify the pins to be used (BSP_LED1:BSP_LED4)
 *						and the pin direction (OUT - write).
 *					Open a GPIO device for reading the switches SW1 & SW2.
 *					Specify the pins to be used (BSP_BUTTON1, BSP_BUTTON2)
 *						and the pin direction (IN - read).
 * 					Each open operation returns a handle to the GPIO device.
 *
 ***************************************************************************/
 
 void LED_1_4_Init()
 {
 	/* Open a GPIO device for writing to the LEDs */
 	led_file1 = fopen("gpio:write", (char_ptr) &pins1);
 	
 	/* Open a GPIO device for reading the switches. */
 	sw_file = fopen("gpio:read", (char_ptr) &pins6);
 	
 	/* Switches are programmed to generate an interrupt off the falling edge
 		when they are pressed */
 	/* Specify <handle>, <operation>, <interrupt service routine> */
 	ioctl(sw_file, GPIO_IOCTL_SET_IRQ_FUNCTION, Switch_Read);	
 	ioctl(sw_file, GPIO_IOCTL_ENABLE_IRQ, NULL);	// Enable the interrupt.
 	
 }
 
/****************************************************************************
 *
 * Function Name  : ADC_Init
 * Returned Value : None
 *
 * Operation	  : Initialises the ADC device by opening an ADC Device
 *						and two ADC channels..
 *					Starts sampling on Analog-to-Digital channel 0 (AN0).
 *					Starts sampling on Analog-to-Digital channel 1 (AN1). 
 *
 ***************************************************************************/
 
 void ADC_Init(void)
 {
	uint_8 x = 0;
	
	/* open ADC device */
	adc_file1 = fopen("adc:",(const char*)&adc_init);
	
	if(adc_file1 == NULL) // Check for correst opening
	{
		/* That's not good */
		x += 1; // Breakpoint line. Used for debugging.
	}
	
	/* Open ADC channel 0 (AN0). */
	adc_file2 = fopen("adc:ch0", (const char*)&adc_channel_param0);

	if(adc_file2 == NULL) // Check for correct opening
	{
		/* That's not good */
		x += 1;	// Breakpoint line. Used for debugging.
	}

	
	/* Open ADC channel 1 (AN1). */
	adc_file3 = fopen("adc:ch1", (const char*)&adc_channel_param1);

	if(adc_file3 == NULL) // Check for correct opening
	{
		/* That's not good */
		x += 1;	// Breakpoint line. Used for debugging.
	}
	
	/* Start sampling ADC channels 0 & 1 (AN0, AN1). */
	if(!adc_triggered)
	{
		/* Trigger ADC channel 0 (AN0). */
		ioctl(adc_file1, ADC_IOCTL_FIRE_TRIGGER, (pointer) MY_TRIGGER_0);
		
		/* Trigger ADC channel 1 (AN1). */
		ioctl(adc_file1, ADC_IOCTL_FIRE_TRIGGER, (pointer) MY_TRIGGER_1);
	
		adc_triggered = 1;
		
	}
	
	

 }
 
 
/****************************************************************************
 *
 * Function Name  : Switch_Read
 * Returned Value : None
 *
 * Operation	  : Callback function called as an interrupt service routine 
 *                   when a switch is pressed.
 *					Determines which switch was pressed (SW1 or SW2) and
 *						Sends the information to the host.
 *
 ***************************************************************************/
 
 void Switch_Read(void)
 {
// 	uint_8 sw_status;
 	
 	/* Determine which switch has been pressed and send the information to 
 		the Host */
 	ioctl(sw_file, GPIO_IOCTL_READ, &pins6);	// Read the switch status.
 	if((pins6[0] & GPIO_PIN_STATUS) == GPIO_PIN_STATUS_1)	// SW2 pressed?
 	{
 		g_logger.rpt_buf[0] = 2;	// Yes! SW2 pressed. Send data to host.
 		(void)USB_Class_EP2_Send_Data(USB_EP2, g_logger.rpt_buf, PC_BUFFER_SIZE);
 	}
 	if((pins6[1] & GPIO_PIN_STATUS) == GPIO_PIN_STATUS_1)	// SW1 pressed?
 	{
 		g_logger.rpt_buf[0] = 1;	// Yes! SW1 pressed. Send data to host.
 		(void)USB_Class_EP2_Send_Data(USB_EP2, g_logger.rpt_buf, PC_BUFFER_SIZE);
 		
 	}

 	
 }
 
 /****************************************************************************
 *
 * Function Name  : READ_ADC_ONCE
 * Returned Value : None
 *
 * Operation	  : Read analog-to-digital converter channels once. 
 *                  Called in response to receiving a READ_ANALOG_DATA 
 *					 command on EP3.
 *					AN0 and AN1 result buffers are read and the result 
 *						sent back to the host via EP2.
 *					
 *
 ***************************************************************************/
 
 void READ_ADC_ONCE(void)
 {
	ADC_RESULT_STRUCT an0_data, an1_data;
	
	uint_8 x = 0;
	
	/* Read ADC channel 0 (AN0) result. */
//	if(read(adc_file2, &an0_data, sizeof(an0_data)) )
//	{
		/* Place result in transmit buffer */
//		g_logger.rpt_buf[0] = ((an0_data.result >> 8) & 0xFF);
//		g_logger.rpt_buf[1] = (an0_data.result & 0xFF);
		
//	}
//	else // check for correct read
//	{
//		x += 1;	// Breakpoint line. Used for debugging.
//	}
	
	/* Read ADC channel 1 (AN1) result. */
//	if(read(adc_file3, &an1_data, sizeof(an1_data)) )
//	{
		/* Place result in transmit buffer */
//		g_logger.rpt_buf[2] = ((an1_data.result >> 8) & 0xFF);
//		g_logger.rpt_buf[3] = (an1_data.result & 0xFF);
		
//	}
//	else // check for correct read
//	{
//		x += 1;	// Breakpoint line. Used for debugging.
//	}
	
	for(x=0;x<PC_BUFFER_SIZE;x++)
	{
		g_logger.rpt_buf[x] = x + 30;
	}
	/* Transmit result to host */
	(void)USB_Class_EP4_Send_Data(USB_EP4, g_logger.rpt_buf, PC_BUFFER_SIZE);
	
 	
 }
 
 void writeToOutBuffer(char[] input)
 {
 	
 }

/****************************************************************************
 *
 * Function Name  : EP1_3_PACKET_REC()
 * Returned Value : None
 *
 * Operation	  : Checks for the arrival of a packet at EPn where n(1,3)
 *						and processes received packets.
 *					The  structures ep1_rx_ctrl and ep3_rx_ctrl (declared in
 *						usb_logger.c) are used for controlling packet
 *						reception.
 *					The arrival of a packet is indicated 
 *						by the flag epn_rx_ctrl.pkt_rec.
 *					Received packets are transferred to the 
 *						receive packet buffer epn_rx_ctrl.ep_pkt_buf[].
 *					The size of a received packet is indicated by
 *						epn_rx_ctrl.len.
 *                   
 *
 ***************************************************************************/
 void EP1_3_PACKET_REC(void)
 {
 	uint_8		count, command;
 	uint_32   	byte_count;			// 
 	EP_RX_CTRL_PTR ep1ctrlPtr;		// Pointer for an EP1 control structure
 	EP_RX_CTRL_PTR ep3ctrlPtr;		// Pointer for an EP3 control structure
 	
 	/*  */
 	ep1ctrlPtr = &ep1_rx_ctrl;		// Set the pointer to the EP1 control structure
 	ep3ctrlPtr = &ep3_rx_ctrl;		// Set the pointer to the EP3 control structure
 	
 	/* Check for an EP1 received packet */
 	if(ep1ctrlPtr->pkt_rec == TRUE)	
 	{
 		/* EP1 packet has arrived */
 		/* Transfer the packet to the EP1 receive packet buffer ep_pht_buf[]. */
 		byte_count = ep1ctrlPtr->len;	// Packet size
 		for(count = 0; count < ep1ctrlPtr->len; count++)
 		{
 			ep1ctrlPtr->ep_pkt_buf[count] = *ep1ctrlPtr->buffer_ptr++;
 		}
 		
 		/* Clear packet received flag */
 		ep1ctrlPtr->pkt_rec = FALSE;
 		
 		/* Check for an overrun error */
 		if(ep1ctrlPtr->overrun_err == TRUE)
 		{
 			/* Ignore for now. */
 			ep1ctrlPtr->overrun_err = FALSE;
 		}
 		
 		/* Process the EP1 command: EP1 controls LED(1:2) */
 		command = ep1ctrlPtr->ep_pkt_buf[0];	// Command is the first byte in the buffer
 		switch(command)
 		{
 			case LEDS_OFF:	// both LEDs off
 				ioctl(led_file1, GPIO_IOCTL_WRITE_LOG0, &pins1);
 				break;
 				
 			case LED1_ON:	// LED1 on
 				ioctl(led_file1, GPIO_IOCTL_WRITE_LOG1, &pins2);
 				break;
 				
 			case LED2_ON:	// LED2 on
 				ioctl(led_file1, GPIO_IOCTL_WRITE_LOG1, &pins3);
 				break;
 				
 		}
 	}
 	
 	
  	/* Check for an EP3 received packet */
 	if(ep3ctrlPtr->pkt_rec == TRUE)	
 	{
 		/* EP3 packet has arrived */
 		/* Transfer the packet to the EP3 receive packet buffer ep_pht_buf[]. */
 		byte_count = ep3ctrlPtr->len;	// Packet size
 		for(count = 0; count < ep3ctrlPtr->len; count++)
 		{
 			ep3ctrlPtr->ep_pkt_buf[count] = *ep3ctrlPtr->buffer_ptr++;
 		}
 		
 		/* Clear packet received flag */
 		ep3ctrlPtr->pkt_rec = FALSE;
 		
 		/* Check for an overrun error */
 		if(ep3ctrlPtr->overrun_err == TRUE)
 		{
 			/* Ignore for now. */
 			ep3ctrlPtr->overrun_err = FALSE;
 		}
 		
 		/* Process the EP3 command: EP3 controls LED4*/
 		command = ep3ctrlPtr->ep_pkt_buf[0];	// Command is the first byte in the buffer
 		switch(command)
 		{
 			case WRITE_LEDS:	// Write data to LED4
 				switch(ep3ctrlPtr->ep_pkt_buf[1])
 				{
 					case LED4_ON:	// LED4 On
 						ioctl(led_file1, GPIO_IOCTL_WRITE_LOG1, &pins5);
 						break;
 						
 					case LED4_OFF:	// LED4 Off
 						ioctl(led_file1, GPIO_IOCTL_WRITE_LOG0, &pins5);
 						break;
 				}
 				break;
 				
 			case READ_ANALOG_DATA:	// Read analog data from the ADC
 				READ_ADC_ONCE();	// Take one reading on AN0
 				break;
 				
 				
 		}
 	}
	
 }

